using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Ruby;
using Ruby.Hosting;


namespace IronLogo
{
    public partial class LogoWindow : Form
    {
        [DllImport("kernel32")]
        static extern bool AllocConsole();

        [DllImport("kernel32")]
        static extern bool FreeConsole();

        public Point TurtlePoint
        {
            get { return this.turtlePoint; }
        }

        public Graphics TurtleHome
        {
            get { return this.turtleHome; }
        }

        public GraphicsPath TurtlePath
        {
            get { return this.turtlePath; }
        }



        private Point turtlePoint;
        private Graphics turtleHome;
        private GraphicsPath turtlePath;
        private IScriptEngine scriptengine;
        private IScriptScope scriptscope;
        private bool consoleopen = false;
        private System.Threading.Thread consolethread;

        public LogoWindow()
        {
            InitializeComponent();
            InitializePortal();
            Timer t = new Timer();
            t.Interval = 50;
            t.Tick += new EventHandler(t_Tick);
            this.FormClosing += new FormClosingEventHandler(LogoWindow_FormClosing);
            t.Enabled = true;
        }

        void LogoWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (consoleopen)
            {
                //HACK:  This is all one big hack, couldn't find a graceful way to close the console
                consolethread.Abort();
                while (consolethread.IsAlive) { }
                FreeConsole();
                consoleopen = false;
            }
        }

        void t_Tick(object sender, EventArgs e)
        {
            this.portalView.Refresh();
        }


      
        public void MoveTurtle(Point p)
        {
            MoveTurtle(TurtlePoint, p);
        }

        public void MoveTurtle(int x, int y)
        {
            MoveTurtle(new Point(x, y));
        }

        

        private delegate void MoveTurtleDelegate(Point p1, Point p2);
        public void MoveTurtle(Point p1, Point p2)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new MoveTurtleDelegate(MoveTurtle), new object[] { p1, p2 });
            }
            Pen pen = new Pen(Brushes.Black);
            pen.CustomEndCap = TriangleEndCap.GetTriangleEndCap();
            this.turtlePath.AddLine(p1, p2);
            this.turtleHome.FillRectangle(Brushes.White, 0f, 0f, this.portalView.Image.Width, this.portalView.Image.Height);
            this.turtleHome.DrawPath(pen, this.turtlePath);
            this.turtlePoint = p2;
           
                    
        }

        

        public void MoveTurtle(int x1, int y1, int x2, int y2)
        {
            MoveTurtle(new Point(x1, y1), new Point(x2, y2));
        }

        public void InitializePortal()
        {
            Bitmap b = new Bitmap(this.portalView.Width, this.portalView.Height);
            this.turtlePoint = new Point(this.portalView.Width/2, this.portalView.Height/2);
            this.portalView.Image = Image.FromHbitmap(b.GetHbitmap());
            this.turtleHome = Graphics.FromImage(this.portalView.Image);
            this.turtleHome.FillRectangle(Brushes.White, 0f, 0f, b.Width, b.Height);
            //Move the turtle just one pixel up just to get it drawn
            this.turtlePath = new GraphicsPath();
            MoveTurtle(this.turtlePoint.X, this.turtlePoint.Y, this.turtlePoint.X, this.turtlePoint.Y -1);
        }

        private class TriangleEndCap
        {
            
            public static System.Drawing.Drawing2D.CustomLineCap  GetTriangleEndCap()
            {
                System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
                Point[] triangle = new Point[3];
                triangle[0] = new Point(0, 5);
                triangle[1] = new Point(5, 0);
                triangle[2] = new Point(-5, 0);
                gp.AddPolygon(triangle);
                return new System.Drawing.Drawing2D.CustomLineCap(null, gp);
            }

        }

        public void PassScopeAndEngine(IScriptScope scope, IScriptEngine engine)
        {
            this.scriptscope = scope;
            this.scriptengine = engine;
        }

        private void applyIronLogoScriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "IronLogo Files (*.ilogo)|*.ilogo|All Files (*.*)|*.*";
            ofd.Title = "Apply An IronLogo File...";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                this.scriptengine.Execute(this.scriptscope, this.scriptengine.CreateScriptSourceFromFile(ofd.FileName));
                
            }
        }

        private void openConsoleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            consolethread = new System.Threading.Thread(new System.Threading.ThreadStart(RunConsole));
            consolethread.Start();
                        
        }

        private void RunConsole()
        {
            if (AllocConsole())
            {
                this.consoleopen = true;
                Ruby.Hosting.RubyCommandLine rubycommandline = new RubyCommandLine(new Ruby.Runtime.RubyContext(ScriptDomainManager.CurrentManager));
                Microsoft.Scripting.Shell.SuperConsole superconsole = new Microsoft.Scripting.Shell.SuperConsole(rubycommandline, this.scriptengine, true);
                rubycommandline.Run(this.scriptengine, superconsole, new Ruby.Hosting.RubyConsoleOptions());
                //Now that it's open how do we close it?
                
            }
        }




    }
}